﻿using System;
using System.Configuration;
using System.Data;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace CVsharp.WebLib.Cache
{
    /// <summary>
    ///WebHelper 的摘要说明
    /// </summary>
    public class UsersOnline
    {
        private readonly int OFFLINEDIFF = Convert.ToInt16(ConfigurationManager.AppSettings["OFFLINEDIFF"]);
        private readonly int REMOVEDIFF = Convert.ToInt16(ConfigurationManager.AppSettings["REMOVEDIFF"]);
        private readonly string USERNAME = ConfigurationManager.AppSettings["ONLINE_SESSION_USERNAME"];

        /// <summary>
        /// 获取在线
        /// </summary>
        public void CheckOnline()
        {
            if (HttpContext.Current.Application["OnlineTalbe"] == null)
            {
                CashTableInit();
            }
            //从Application获取数据表、获取SessionID
            var dtOnline = (DataTable) HttpContext.Current.Application["OnlineTalbe"];
            string sessionId = HttpContext.Current.Session.SessionID;
            //数据表中是否有我的记录
            DataRow drFind = dtOnline.Rows.Find(sessionId);
            if (drFind != null)
            {
                //有；更新我的状态
                drFind["LastActiveTime"] = DateTime.Now;
                drFind["VisitorIP"] = GetRealIP();
                drFind["UserWhere"] = AtWhere();
                //用户由访客状态变为了登陆会员、或反之
                if (!string.IsNullOrEmpty(GetSessionbyName(USERNAME)))
                {
                    drFind["VisitorName"] = GetSessionbyName(USERNAME);
                    drFind["LoginTime"] = GetSessionbyName("LoginTime");
                }
                else
                {
                    drFind["VisitorName"] = "游客";
                    drFind["LoginTime"] = DateTime.Now;
                }
            }
            else
            {
                //无；加入关于我的在线信息
                DataRow drNew = dtOnline.NewRow();
                drNew["SessionID"] = sessionId;
                drNew["VisitorName"] = "游客";
                drNew["LastActiveTime"] = DateTime.Now;
                drNew["LoginTime"] = DateTime.Now;
                drNew["VisitorIP"] = GetRealIP();
                drNew["UserWhere"] = AtWhere();
                dtOnline.Rows.Add(drNew);
            }
            //如果没有人正在执行删除且离上次删除的时间间隔超过设定值
            TimeSpan tsRemove = DateTime.Now - Convert.ToDateTime(GetApplication("LastRemove"));
            if (tsRemove.Seconds > REMOVEDIFF && GetApplication("Removing") == "n")
            {
                //锁定，我正在删除过期用户
                HttpContext.Current.Application.Lock();
                SetApplication("Removing", "y");
                HttpContext.Current.Application.UnLock();
                //不知道Rows.Count是否随循环减少，如果是效率就大于foreach且这里不能使用foreach
                for (int i = 0; i < dtOnline.Rows.Count; i++)
                {
                    DataRow drDel = dtOnline.Rows[i];
                    TimeSpan ts = DateTime.Now - Convert.ToDateTime(drDel["LastActiveTime"]);
                    if (ts.Minutes > OFFLINEDIFF)
                    {
                        dtOnline.Rows.Remove(drDel);
                    }
                }
                //删完了，Response.Write("删除完毕") ;
                HttpContext.Current.Application.Lock();
                SetApplication("Removing", "n");
                SetApplication("LastRemove", DateTime.Now.ToString());
                HttpContext.Current.Application.UnLock();
            }
            //处理过的数据表放回Application
            dtOnline.AcceptChanges();
            HttpContext.Current.Application.Lock();
            HttpContext.Current.Application["DataTalbeOnline"] = dtOnline;
            HttpContext.Current.Application.UnLock();
        }

        /// <summary>
        /// 创建表
        /// </summary>
        public void CashTableInit()
        {
            var dt = new DataTable("OnlineTalbe");
            dt.Columns.Add("SessionID", typeof (string));
            dt.Columns.Add("VisitorName", typeof (string));
            dt.Columns.Add("LastActiveTime", typeof (DateTime));
            dt.Columns.Add("LoginTime", typeof (DateTime));
            dt.Columns.Add("VisitorIP", typeof (string));
            dt.Columns.Add("UserWhere", typeof (string));
            dt.Columns["SessionID"].Unique = true;
            dt.PrimaryKey = new[] {dt.Columns["SessionID"]};

            HttpContext.Current.Application["OnlineTalbe"] = dt;
            HttpContext.Current.Application["LastRemove"] = DateTime.Now.ToString();
            HttpContext.Current.Application["Removing"] = "n";
        }

        public string GetSessionbyName(string sessionname)
        {
            string sessionvalue = "";
            try
            {
                sessionvalue = HttpContext.Current.Session[sessionname].ToString().Trim();
            }
            catch
            {
            }
            return sessionvalue;
        }

        public string GetSessionbyName(string sessionname, string sessiondefaultvalue)
        {
            string sessionvalue = sessiondefaultvalue;
            try
            {
                sessionvalue = HttpContext.Current.Session[sessionname].ToString().Trim();
            }
            catch
            {
            }
            return sessionvalue;
        }

        /// <summary>
        /// 获取当前访问页
        /// </summary>
        /// <param name="apcname"></param>
        /// <returns></returns>
        private string GetApplication(string apcname)
        {
            return HttpContext.Current.Application[apcname].ToString();
        }

        public void SetApplication(string apcname, string apcvalue)
        {
            HttpContext.Current.Application[apcname] = apcvalue;
        }

        /// <summary>
        /// 返回用户当前位置
        /// </summary>
        private string AtWhere()
        {
            var sb = new StringBuilder();
            sb.Append(HttpContext.Current.Request.ServerVariables["url"]);
            if (HttpContext.Current.Request.ServerVariables["QUERY_STRING"] != String.Empty)
            {
                sb.Append("?");
                sb.Append(HttpContext.Current.Request.ServerVariables["QUERY_STRING"]);
            }
            return sb.ToString();
        }

        /// <summary>
        /// 是否ip格式
        /// </summary>
        /// <param name="strIP">待检测字符串</param>
        /// <returns></returns>
        public Boolean IsIPAddress(string strIP)
        {
            if (string.IsNullOrEmpty(strIP) || strIP.Length < 7 || strIP.Length > 15) return false;
            const string regformat = @"^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$";
            var regex = new Regex(regformat, RegexOptions.IgnoreCase);
            return regex.IsMatch(strIP);
        }

        /// <summary>
        /// 获得访问者IP
        /// </summary>
        /// <returns></returns>
        public string GetRealIP()
        {
            string result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
            if (!string.IsNullOrEmpty(result))
            {
                //可能有代理
                if (result.IndexOf(".") == -1) //没有"."肯定是非IPv4格式
                    result = null;
                else
                {
                    if (result.IndexOf(",") != -1)
                    {
                        //有","，估计多个代理。取第一个不是内网的IP。
                        result = result.Replace(" ", "").Replace("", "");
                        string[] temparyip = result.Split(",;".ToCharArray());
                        foreach (string t in temparyip)
                        {
                            if (IsIPAddress(t)
                                && t.Substring(0, 3) != "10."
                                && t.Substring(0, 7) != "192.168"
                                && t.Substring(0, 7) != "172.16.")
                            {
                                return t; //找到不是内网的地址
                            }
                        }
                    }
                    else if (IsIPAddress(result)) //代理即是IP格式
                        return result;
                    else
                        result = null; //代理中的内容 非IP，取IP
                }
            }
            //string IpAddress = ( HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null && HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != String.Empty )HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] : HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
            if (HttpContext.Current != null)
            {
                string IpAddress = (HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null
                                    && HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != String.Empty)
                                       ? HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]
                                       : HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
            }


            if (string.IsNullOrEmpty(result))
                if (HttpContext.Current != null) result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];

            if (string.IsNullOrEmpty(result))
                if (HttpContext.Current != null) result = HttpContext.Current.Request.UserHostAddress;
            return result;
        }

    }
}